#ifndef RECTYPE_H_
#define RECTYPE_H_

#include <stdint.h>

// for debug purposes
#if _DEBUG
#include <iostream>
#endif

namespace opsrc 
{
		namespace stdf 
		{
		
		// STDF specs Version 4.0 page 9 of 103
		
		enum rec_typ  {
			file_data            =   0, // information about stdf file
			lot_data             =   1, // data collected on perlot basis
			wafer_data           =   2, // data collected per wafer
			part_data            =   5, // data collected on per part basis
			test_program_data    =  10, // data collectd per test in the test program
			test_execution_data  =  15, // data collected per test execution
			program_segment_data =  20, // data collected per progam segment
			generic_data         =  50, // generic data
			image_software       = 180, // reserved for used by image software
			ig900_software       = 181, // reserved for use by IG900 software
			rt_unk               = 0xFF // 255
		};
		
		enum  rec_sub_typ {
			far   = 10,	// file attributes record
			atr   = 20, // audit trail record
			mir   = 10, // master information record
			mrr   = 20, // master results record
			pcr   = 30, // part count record
			hbr   = 40, // hardware bin record
			sbr   = 50, // software bin record
			pmr   = 60, // pin map record
			pgr   = 62, // pin group record
			plr   = 63, // pin list record
			rdr   = 70, // retest data record
                        sdr   = 80, // site description20110513_d.txt record
			wir   = 10, // wafer information record
			wrr   = 20, // wafer results record
			wcr   = 30, // wafer configuration record
			pir   = 10, // part information record
			prr   = 20, // part results record
			tsr   = 30, // test synospsis record
			ptr   = 10, // parametric test record
			mpr   = 15, // multi-result parametric record 
			ftr   = 20, // functional test record
			bps   = 10, // begin program section record
			eps   = 20, // end program test record
			gdr   = 10, // generic data record
			dtr   = 30,  // data text record
			rst_unk = 0xFF  // 255
		
		} ;
		
		
		enum stdf_rec {
			FAR   = 0,	// file attributes record
			ATR   = 1, // audit trail record
			MIR   = 2, // master information record
			MRR   = 3, // master results record
			PCR   = 4, // part count record
			HBR   = 5, // hardware bin record
			SBR   = 6, // software bin record
			PMR   = 7, // pin map record
			PGR   = 8, // pin group record
			PLR   = 9, // pin list record
			RDR   = 10, // retest data record
			SDR   = 11, // site description record
			WIR   = 12, // wafer information record
			WRR   = 13, // wafer results record
			WCR   = 14, // wafer configuration record
			PIR   = 15, // part information record
			PRR   = 16, // part results record
			TSR   = 17, // test synospsis record
			PTR   = 18, // parametric test record
			MPR   = 19, // multi-result parametric record 
			FTR   = 20, // functional test record
			BPS   = 21, // begin program section record
			EPS   = 22, // end program test record
			GDR   = 23, // generic data record
			DTR   = 24,  // data text record
			UNK  = 0xFF // unknown	, 255

		};

		
		enum cpu_typ {
			dec = 0,            // digital vax 
			sun = 1,            // sun sparc  
			x86 = 2,            // intel amd based microprocessors
			unk = 0xFF          // unknown type
		};


		
		enum endian { big_endian = 0, little_endian = 1 };
		
		
		typedef	uint8_t			byte;
		typedef	char*			CN_pchar;
		typedef	char			C1_char;
		typedef	uint8_t			U1_uint8;
		typedef	uint16_t		U2_uint16;
		typedef	uint32_t		U4_uint32;
		typedef	int8_t			I1_int8;
		typedef	int16_t			I2_int16;
		typedef	int32_t			I4_int32;
		typedef	float			R4_float32;
		typedef	double			R8_float64;
		typedef	char*			Bn_pchar;  // 1st byte is count
		typedef	char			B1_char1;  // lst 
		typedef	char*			Dn_pchar;  // 1st 2 bytes is count
		typedef	char			N1_char;   // first 4 bits (lower) is data, next upper 4 bits as next set of data
		
			

		struct stdf_rec_typ_pair 
		{
			rec_typ rectyp;
			rec_sub_typ recsubtyp;
		};		
		
		struct StdfHelp
		{


		
			inline static stdf_rec checkStdfRecHeader(char* pFileBytePosition) 
			{
				char* pfirstByte = (pFileBytePosition);     // rec type byte
				char* psecondByte = pFileBytePosition + 1;  // rec sub type byte
				
				// file data record type
				unsigned int rectype = static_cast<unsigned int> (*pfirstByte);
				unsigned int subrectype = static_cast<unsigned int> (*psecondByte);
				
				if (rectype == file_data) {
					if (subrectype == far) return FAR;
					if (subrectype == atr) return ATR;
					return UNK;
				}
				
				// per lot basis record type
				if (rectype == lot_data ) {
					if (subrectype == mir) return MIR;
					if (subrectype == mrr) return MRR;
					if (subrectype == pcr) return PCR;
					if (subrectype == hbr) return HBR;
					if (subrectype == pmr) return PMR;
					if (subrectype == sbr) return SBR;
					if (subrectype == pgr) return PGR;
					if (subrectype == plr) return PLR;
					if (subrectype == rdr) return RDR;
					if (subrectype == sdr) return SDR;
					return UNK;
				}
				
				// per wafer basis record type
				if (rectype == wafer_data ) {
					if (subrectype == wir) return WIR;
					if (subrectype == wrr) return WRR;
					if (subrectype == wcr) return WCR;
					return UNK;
				}	
				
				// per part basis record type
				if (rectype == part_data ) {
					if (subrectype == pir) return PIR;
					if (subrectype == prr) return PRR;
					return UNK;
				}	
				
				
				// Data collected per test in test program
				if (rectype == test_program_data ) {
					if (subrectype == tsr) return TSR;
					return UNK;
				}	
				
				// Data collected per test execution
				if (rectype == test_execution_data ) {
					if (subrectype == ptr) return PTR;
					if (subrectype == mpr) return MPR;
					if (subrectype == ftr) return FTR;
					return UNK;
				}	
					
					
				// Data collected per program segment
				if (rectype == program_segment_data ) {
					if (subrectype == bps) return BPS;
					if (subrectype == eps) return EPS;
					return UNK;
				}		
				
				// Generic data
				if (rectype == generic_data ) {
					if (subrectype == gdr) return GDR;
					if (subrectype == dtr) return DTR;
					return UNK;
				}		
				
				return UNK;				
			}

                        inline static const char* getStdfFieldStringName(stdf_rec i) {
                            const char* stdf_fields_char[] = {
                                "FAR\0",
                                "ATR\0",
                                "MIR\0",
                                "MRR\0",
                                "PCR\0",
                                "HBR\0",
                                "SBR\0",
                                "PMR\0",
                                "PGR\0",
                                "PLR\0",
                                "RDR\0",
                                "SDR\0",
                                "WIR\0",
                                "WRR\0",
                                "WCR\0",
                                "PIR\0",
                                "PRR\0",
                                "TSR\0",
                                "PTR\0",
                                "MPR\0",
                                "FTR\0",
                                "BPS\0",
                                "EPS\0",
                                "GDR\0",
                                "DTR\0"
                            };

                            return stdf_fields_char[i];
                        }


			
			inline static stdf_rec_typ_pair getStdfRefTypPair(stdf_rec stdfrec) 
			{
				stdf_rec_typ_pair val;
				
				switch (stdfrec)
				{
					case FAR:
						val.rectyp= file_data;
						val.recsubtyp = far;
						break;
					case ATR:
						val.rectyp = file_data;
						val.recsubtyp = atr;
						break; 	
					case MIR:
						val.rectyp = lot_data;
						val.recsubtyp = mir;
						break;
					case MRR:
						val.rectyp = lot_data;
						val.recsubtyp = mrr;
						break;
					case PCR:
						val.rectyp = lot_data;
						val.recsubtyp = pcr;
						break;
					case HBR:
						val.rectyp = lot_data;
						val.recsubtyp = hbr;
						break;
					case PMR:
						val.rectyp = lot_data;
						val.recsubtyp = pmr;
						break;
					case SBR:
						val.rectyp = lot_data;
						val.recsubtyp = sbr;
						break;
					case PGR:
						val.rectyp = lot_data;
						val.recsubtyp = pgr;
						break;
					case PLR:
						val.rectyp = lot_data;
						val.recsubtyp = plr;
						break;
					case WIR:
						val.rectyp = wafer_data;
						val.recsubtyp = wir;
						break;
					case WRR:
						val.rectyp = wafer_data;
						val.recsubtyp = wrr;
						break;	
					case WCR:
						val.rectyp = wafer_data;
						val.recsubtyp = wcr;
						break;
					case PIR:
						val.rectyp = part_data;
						val.recsubtyp = pir;
						break;
					case PRR:
						val.rectyp = part_data;
						val.recsubtyp = prr;
						break;
					case TSR:
						val.rectyp = test_program_data;
						val.recsubtyp = tsr;
						break;
					case PTR:
						val.rectyp = test_execution_data;
						val.recsubtyp = ptr;
						break;
					case MPR:
						val.rectyp = test_execution_data;
						val.recsubtyp = mpr;
						break;
					case FTR:
						val.rectyp = test_execution_data;
						val.recsubtyp = ftr;
						break;
					case BPS:
						val.rectyp = program_segment_data;
						val.recsubtyp = bps;
						break;
					case EPS:
						val.rectyp = program_segment_data;
						val.recsubtyp = eps;
						break;
					case GDR:
						val.rectyp = program_segment_data;
						val.recsubtyp = gdr;
						break;
					case DTR:
						val.rectyp = generic_data;
						val.recsubtyp = dtr;
						break;					
					default:
						val.rectyp = rt_unk;
						val.recsubtyp = rst_unk;
						break;
				};
				
				return val;
			}
			
		};
		
		// Dummy class used as datatype
		// A Nibble is represented by 4 bits or 1/2 a byte
		struct Nibble { };
		
		enum gdr_data_typ {
			  B0 = 0,
			  U1 = 1,
			  U2 = 2,
			  U4 = 3,
			  I1 = 4,
			  I2 = 5,
			  I4 = 6,
			  R4 = 7,
			  R8 = 8,
			  CN = 10,
			  BN = 11,
			  DN = 12,
			  N1 = 13,
			  UK = 99
/*			
			0 = B*0 Special pad field, of length 0 (See note below)
			1 = U*1 One byte unsigned integer
			2 = U*2 Two byte unsigned integer
			3 = U*4 Four byte unsigned integer
			4 = I*1 One byte signed integer
			5 = I*2 Two byte signed integer
			6 = I*4 Four byte signed integer
			7 = R*4 Four byte floating point number
			8 = R*8 Eight byte floating point number
			10 = C*n Variable length ASCII character string
			(first byte is string length in bytes)
			11 = B*n Variable length binary data string
			(first byte is string length in bytes)
			12 = D*n Bit encoded data
			(first two bytes of string are length in bits)
			13 = N*1 Unsigned nibble		
*/			
		};		
		
		inline static gdr_data_typ checkGdrFieldType(char* buf) {
			
			gdr_data_typ result = UK;
			
			// convert to unsigned integer value
			unsigned int val = static_cast<unsigned int> (*buf);  
			switch (val) {
			  case B0:
			  	result = B0;
			  	break;
			  case U1:
			    result = U1;
			    break;
			  case U2:
			    result = U2;
			    break;
			  case U4:
			  	result = U4;
			  	break;
			  case I1:
			  	result = I1;
			  	break;
			  case I2:
			  	result = I2;
			  	break;
			  case I4:
			  	result = I4;
			  	break;
			  case R4:
			  	result = R4;
			  	break;
			  case R8:
			  	result = R8;
			  	break;
			  case CN:
			  	result = CN;
			  	break;
			  case BN:
			  	result = BN;
			  	break;
			  case DN:
			  	result = DN;
			  	break;
			  case N1:
			  	result = N1;
			  	break;
			  default: 
				break;
			};
			
			return result;
		
		}
	}		// namespace stdf
}			// namespace opsrc


#endif /*RECTYPE_H_*/
